package com.chuangke.metadata.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chuangke.admin.data.builder.UserDataBuilder;
import com.chuangke.common.data.builder.DataBuildConfig;
import com.chuangke.common.data.builder.DataBuilder;
import com.chuangke.common.db.page.CkPageQuery;
import com.chuangke.framework.util.TreeUtils;
import com.chuangke.metadata.dao.SysGridColumnDao;
import com.chuangke.metadata.dao.SysGridFormulaDao;
import com.chuangke.metadata.dao.SysGridModelDao;
import com.chuangke.metadata.dao.SysGridVarDao;
import com.chuangke.metadata.entity.SysGridColumn;
import com.chuangke.metadata.entity.SysGridFormula;
import com.chuangke.metadata.entity.SysGridModel;
import com.chuangke.metadata.entity.SysGridVar;
import com.chuangke.metadata.service.SysGridModelService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;

@Service
public class SysGridModelServiceImpl implements SysGridModelService {
	
	public static final String CACHE_NAME = "sys_grid_model";

	@Autowired
	private SysGridModelDao sysGridModelDaoService;
	@Autowired
	private SysGridColumnDao sysGridColumnDaoService;
	@Autowired
	private SysGridFormulaDao sysGridFormulaDaoService;
	@Autowired
	private SysGridVarDao sysGridVarDaoService;
	
	@Override
	@Transactional(rollbackFor = Throwable.class)
	@CacheEvict(cacheNames = CACHE_NAME, key = "#model.id")
	public void saveSysGridMode(SysGridModel model) {
		sysGridModelDaoService.saveOrUpdate(model) ;
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	@CacheEvict(cacheNames = CACHE_NAME, key = "#model.id")
	public String save(SysGridModel model) {
		sysGridModelDaoService.save(model);
		saveSysGridModelColumn(model);
		return model.getId();
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	@CacheEvict(cacheNames = CACHE_NAME, key = "#model.id")
	public void update(SysGridModel model) {
		sysGridModelDaoService.updateById(model);
		saveSysGridModelColumn(model);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	@CacheEvict(cacheNames = CACHE_NAME, key = "#model.id")
	public String saveOrUpdate(SysGridModel model) {
		sysGridModelDaoService.saveOrUpdate(model) ;
		saveSysGridModelColumn(model);
		return model.getId();
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	public void delete(List<String> idList) {
		if(CollectionUtils.isEmpty(idList)) {
			return ;
		}
		idList.forEach(id -> ((SysGridModelService) AopContext.currentProxy()).delete(id));
//
//		sysGridModelDaoService.removeBatchByIds(idList);
//		sysGridColumnDaoService
//				.remove(Wrappers.<SysGridColumn>lambdaQuery().in(SysGridColumn::getModelId, idList));
//		sysGridFormulaDaoService
//		.remove(Wrappers.<SysGridFormula>lambdaQuery().in(SysGridFormula::getModelId, idList));
//		sysGridVarDaoService
//		.remove(Wrappers.<SysGridVar>lambdaQuery().in(SysGridVar::getModelId, idList));
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	@CacheEvict(cacheNames = CACHE_NAME, key = "#id")
	public void delete(String id) {
		if(StrUtil.isEmpty(id)) {
			return ;
		}

		sysGridModelDaoService.removeById(id);
		sysGridColumnDaoService
				.remove(Wrappers.<SysGridColumn>lambdaQuery().eq(SysGridColumn::getModelId, id));
		sysGridFormulaDaoService
				.remove(Wrappers.<SysGridFormula>lambdaQuery().eq(SysGridFormula::getModelId, id));
		sysGridVarDaoService
				.remove(Wrappers.<SysGridVar>lambdaQuery().eq(SysGridVar::getModelId, id));
	}

	@Override
	@Cacheable(cacheNames = CACHE_NAME, key = "#id")
	public SysGridModel load(String id) {
		SysGridModel model = sysGridModelDaoService.getById(id);
		if(model == null) {
			return null ;
		}
		
		List<SysGridColumn> columnList = sysGridColumnDaoService
				.list(Wrappers.<SysGridColumn>lambdaQuery().eq(SysGridColumn::getModelId, id).orderByAsc(SysGridColumn::getSort));
		
		initViewParam(columnList) ;
		
		List<SysGridColumn> treeList = TreeUtils.buildTree(columnList);
		
		treeList.sort(Comparator.comparing(SysGridColumn::getSort));
		
		model.setColumns(treeList);
		return model;
	}
	
	private void initViewParam(List<SysGridColumn> columnList) {
		if(CollectionUtils.isEmpty(columnList)) {
			return ;
		}
		columnList.forEach(column -> {
			column.putParam("formatType", column.getFormatType());
			column.putParam("pattern", column.getFormat());
		});
		
	}

	@Override
	public IPage<SysGridModel> page(CkPageQuery page) {
		String fuzzy = (String) page.get("name") ;
		QueryWrapper<SysGridModel> queryWrapper = new QueryWrapper<>() ;
    	if(!StrUtil.isBlank(fuzzy)) {
    		queryWrapper.lambda().like(SysGridModel::getId, fuzzy).or().like(SysGridModel::getName, fuzzy) ;
    	}
		String moduleId=(String) page.get("moduleId") ;
		if(!StrUtil.isBlank(moduleId)) {
			queryWrapper.lambda().eq(SysGridModel::getMoudleId, moduleId);
		}
    	queryWrapper.lambda().orderByAsc(SysGridModel::getId) ;
    	
    	IPage<SysGridModel> result = sysGridModelDaoService.page(page.getPage(),queryWrapper);
    	DataBuilder.of(result.getRecords()).appendBuilder(new UserDataBuilder(), new DataBuildConfig("createdBy", "createdByName"),
                new DataBuildConfig("updatedBy", "updatedByName")).build();
    	
		return result ;
	}
	
	@Override
	@Transactional(rollbackFor = Throwable.class)
	@CacheEvict(cacheNames = CACHE_NAME, key = "#model.id")
	public void saveSysGridModelColumn(SysGridModel model) {
		sysGridColumnDaoService.remove(Wrappers.<SysGridColumn>lambdaQuery().eq(SysGridColumn::getModelId, model.getId()));
		
		if (CollectionUtils.isEmpty(model.getColumns())) {
			return;
		}

		List<SysGridColumn> columnList = TreeUtils.treeToList(model.getColumns());

		columnList.forEach(column -> {
//			column.setId(IdManager.nextId()) ;
			column.setModelId(model.getId());
//			if(!CollectionUtils.isEmpty(column.getChildren())) {
//				column.getChildren().forEach(child -> child.setParentId(column.getId())) ;
//			}
		});

		sysGridColumnDaoService.saveBatch(columnList);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	@CacheEvict(cacheNames = CACHE_NAME, key = "#model.modelId")
	public void addModelCoumn(SysGridColumn column) {
		sysGridColumnDaoService.remove(Wrappers.<SysGridColumn>lambdaQuery().eq(SysGridColumn::getId, column.getId()));
		sysGridColumnDaoService.save(column);
	}

	@Override
	@Transactional(rollbackFor = Throwable.class)
	@CacheEvict(cacheNames = CACHE_NAME, key = "'" + CACHE_NAME + "'")
	public void delModelColumns(List<String> idList) {
		sysGridColumnDaoService
				.remove(Wrappers.<SysGridColumn>lambdaQuery().in(SysGridColumn::getId, idList));
	}

}
